package com.luke.xiaotiaowa.advice;

import cn.hutool.core.util.BooleanUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.luke.xiaotiaowa.context.MainThreadLocal;
import com.luke.xiaotiaowa.events.XtwEvents;
import com.luke.xiaotiaowa.resp.ResponseVo;
import io.micrometer.core.lang.NonNull;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * 封装响应数据
 * 
 * @author xiaotiaowa
 * @create 2023/3/23
 */
@RestControllerAdvice(basePackages = {"com.luke.xiaotiaowa.controller"})
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(@NonNull MethodParameter returnType, @NonNull Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, @NonNull MediaType selectedContentType,
                                  @NonNull Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  @NonNull ServerHttpRequest request, @NonNull ServerHttpResponse response) {
        // String类型不能直接包装
        if (returnType.getGenericParameterType().equals(String.class)) {
            var objectMapper = new ObjectMapper();
            try {
                return objectMapper.writeValueAsString(ResponseVo.builder().data(body).build());
            } catch (JsonProcessingException e) {
                throw XtwEvents.INTERNAL_SERVER_ERROR.get().message(e.getMessage()).cause(e);
            }
        }
        var responseVo = ResponseVo.builder()
                .code(XtwEvents.OK.getStatus())
                .message(XtwEvents.OK.getMessage())
                .data(body)
                .build();
        if (BooleanUtil.isTrue(MainThreadLocal.isPage())) {
            responseVo.setPage(MainThreadLocal.getPage());
            MainThreadLocal.clean();
        }
        return responseVo;
    }
}
